﻿using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Text;
using System.Xml.Serialization;

namespace ExcelExportLib
{
    /// <summary>Cell</summary>
    [XmlRoot("Cell")]
    public class ExcelCell : IXmlSerializable
    {
        /// <summary>Name of cell</summary>
        public string cellName = null;

        /// <summary>Data in cell </summary>
        public string text;
        /// <summary>Type of Data in cell </summary>
        public eCellType type;

        /// <summary>Style of data in cell (color, bold, alignment etc.)</summary>
        private string _cellStyle=null;

        /// <summary>target uri od hyperlink cell</summary>
        private string _hRef;

        public string cellStyle
        {
            get
            {
                if (_cellStyle == null)
                    return ExcelCellStyle.GetStyleForCellType(type);

                return _cellStyle;
            }
            set
            {
                if (_cellStyle != null)
                {
                    if (ExcelCellStyle.styles.ContainsKey(_cellStyle))
                    {
                       ExcelCellStyle.styles[_cellStyle].TimesUsed -= 1;
                    }
                }
                _cellStyle = value;
                if (ExcelCellStyle.styles.ContainsKey(_cellStyle))
                {
                    ExcelCellStyle.styles[_cellStyle].TimesUsed += 1;
                }

            }
        }

        /// <summary>Cell position in row</summary>
        public int index=1;

        /// <summary>Row wich contains this cell </summary>
        internal ExcelRow parent_row = null;

        public ExcelCellComment comment = null;

        string DecimalSeparator = System.Globalization.CultureInfo.CurrentCulture.NumberFormat.NumberDecimalSeparator;
        string GroupSeparator = System.Globalization.CultureInfo.CurrentCulture.NumberFormat.NumberGroupSeparator;

        /// <summary> For serialization only </summary>
        public ExcelCell() {}

        public ExcelCell(eDateType edt, DateTime date)
        {
            this.text = date.GetExcelDate();
            switch (edt)
            {
                case eDateType.Date:
                    type = eCellType.Date;
                    ExcelCellStyle.styles["Date"].TimesUsed += 1;
                    break;
                case eDateType.DateTime:
                    type = eCellType.DateTime;
                    ExcelCellStyle.styles["DateTime"].TimesUsed += 1;
                    break;
                case eDateType.Time:
                    type = eCellType.Time;
                    ExcelCellStyle.styles["Time"].TimesUsed += 1;
                    break;
            }
        }

        public ExcelCell(long num)
        {
            text = num.ToString();
            type = eCellType.Number;
        }

        public ExcelCell(double num)
        {
            text = num.ToString();
            type = eCellType.Number;
        }

        public ExcelCell(decimal num)
        {
            text = num.ToString();
            type = eCellType.Number;
        }

        public ExcelCell(double num, bool percent)
        {
            if (percent)
            {
                text = num.ToString();
                type = eCellType.Percent;
            }
            else
            {
                text = num.ToString();
                type = eCellType.Number;
            }                
        }
        public ExcelCell(string caption, string hRef)
        {
            text = caption ;
            _hRef = hRef;
            type = eCellType.HyperLink ;
        }

        public ExcelCell(string s)
        {
            text = s;
            type = eCellType.String;
        }

        public ExcelCellPosition GetPosition()
        {
            if (parent_row == null)
                throw new Exception("This cell is not addded to row therefore no cell position exists!");

            if (parent_row.parentTable == null)
                return new ExcelCellPosition(parent_row.index, index);
            else
                return new ExcelCellPosition(parent_row.parentTable.tableName, parent_row.index, index);
        }

        #region IXmlSerializable Members

        public System.Xml.Schema.XmlSchema GetSchema()
        {
            return null;
        }

        public void ReadXml(System.Xml.XmlReader reader)
        {
            throw new NotImplementedException();
        }

        public void WriteXml(System.Xml.XmlWriter writer)
        {
            writer.WriteExcelAttribute("Index", index);
            if(type==eCellType.Formula)
                writer.WriteExcelAttribute("Formula", text);
            writer.WriteExcelAttribute("StyleID", cellStyle);

            if (type== eCellType.HyperLink )
                writer.WriteAttributeString("ss", "HRef", null, _hRef );
            string t = type.ToString();

            switch (type)
            {
                case eCellType.Percent:
                case eCellType.HyperLink:
                    t = "String";
                    break;
                case eCellType.Date:
                case eCellType.DateTime:
                case eCellType.Time:
                    t = "DateTime";
                    break;
            }

            writer.WriteStartElement("Data");
            if(type==eCellType.Formula)
                writer.WriteExcelAttribute("Type", "Number");
            else
                writer.WriteExcelAttribute("Type", t);

            switch (type)
            {
                case eCellType.Formula:
                    writer.WriteString("0");
                    break;
                case eCellType.Percent:
                    writer.WriteString(text+"%");
                    break;
                case eCellType.Number:
                    writer.WriteString(text.Replace(GroupSeparator, string.Empty).Replace(DecimalSeparator, ".")); 
                    break;
                default:
                    writer.WriteString(text);
                    break;
            }

            writer.WriteEndElement();

            //writing comment data
            if ( (comment != null) && (comment.lines.Count!=0))
            {
                writer.WriteStartElement("Comment");
                comment.WriteXml(writer);
                writer.WriteEndElement();
            }

        }
        public override string ToString()
        {
            return string.Concat("Position= ", GetPosition().ToString(), ", CellStyle= ", _cellStyle);
        }
        #endregion
    }
}
